#include "SuperBlock.h"


SuperBlock::SuperBlock(int fd) {
	//goes to the location on the superblock (0)
	lseek(fileDescriptor,0,SEEK_SET);
	read(fd,&fileSysSize,sizeof(int));
	read(fd,&sizeOfBlock,sizeof(int));
	read(fd,&numOfRootINode,sizeof(int));
	read(fd,&numOfFreeBlocksInFileSys,sizeof(int));
	read(fd,&pointerIntoBlockOfFreeBlocks,sizeof(int));
	read(fd,&pointerToTheLastBlockOfFreeBlocks,sizeof(int));
	read(fd,&sizeOfINodeArray,sizeof(int));
	read(fd,&numOfFreeINodesInFileSys,sizeof(int));
	read(fd,&pointerIntoBlockOfFreeINodes,sizeof(int));
	read(fd,&pointerToTheLastBlockOfFreeINodes,sizeof(int));

	totalNumOfBlocks = fileSysSize/sizeOfBlock;
	fileDescriptor = fd;

}

SuperBlock::SuperBlock(int fileSystemSize, int blockSize, int numOfINodes, int fileSysDescriptor) :
	fileSysSize(fileSystemSize), sizeOfBlock(blockSize), numOfRootINode(0), sizeOfINodeArray(numOfINodes),
	numOfFreeINodesInFileSys(numOfINodes), fileDescriptor(fileSysDescriptor), totalNumOfBlocks(fileSystemSize/blockSize) {
	int totalINodeBytes = (numOfINodes*50);
	int totalOccupiedBlocksByINodes;
	//all inode's size fits exactly into an array of blocks
	if ((totalINodeBytes % blockSize) == 0) {
		totalOccupiedBlocksByINodes = totalINodeBytes / blockSize;
	} else {
		totalOccupiedBlocksByINodes = (totalINodeBytes / blockSize) +1;
	}

	numOfOccupiedBlocksByInodes = totalOccupiedBlocksByINodes;
	//the sum of free blocks is the total number of blocks - the number of blocks that occupy the inodes - block 0-2 (part of the superblock)
	//TODO check again when inserting INodes
	numOfFreeBlocksInFileSys = totalNumOfBlocks - totalOccupiedBlocksByINodes - 3;
	//sits in block 1
	pointerIntoBlockOfFreeBlocks = sizeOfBlock*1;
	//sits in block 2
	pointerIntoBlockOfFreeINodes = sizeOfBlock*2;
}

SuperBlock::~SuperBlock() {}

int SuperBlock::getFileSysSize() {
	return fileSysSize;
}

int SuperBlock::getSizeOfBlock() {
	return sizeOfBlock;
}

int SuperBlock::getNumOfRootINode() {
	return numOfRootINode;
}

int SuperBlock::getNumOfFreeBlocksInFileSys() {
	return numOfFreeBlocksInFileSys;
}

int SuperBlock::getPointerIntoBlockOfFreeBlocks() {
	return pointerIntoBlockOfFreeBlocks;
}

int SuperBlock::getPointerToTheLastBlockOfFreeBlocks() {
	return pointerToTheLastBlockOfFreeBlocks;
}

int SuperBlock::getSizeOfINodeArray() {
	return sizeOfINodeArray;
}

int SuperBlock::getNumOfFreeINodesInFileSys() {
	return numOfFreeINodesInFileSys;
}

int SuperBlock::getPointerIntoBlockOfFreeINodes() {
	return pointerIntoBlockOfFreeINodes;
}

int SuperBlock::getPointerToTheLastBlockOfFreeINodes() {
	return pointerToTheLastBlockOfFreeINodes;
}

int SuperBlock::getTotalNumOfBlocks() {
	return totalNumOfBlocks;
}

int SuperBlock::getNumOfOccupiedBlocksByInodes() {
	return numOfOccupiedBlocksByInodes;
}

void SuperBlock::setNumOfFreeBlocksInFileSys(int newNumOfFreeBlocks) {
	numOfFreeBlocksInFileSys = newNumOfFreeBlocks;
}

void SuperBlock::incNumOfFreeBlocksInFileSys() {
	numOfFreeBlocksInFileSys++;
}

void SuperBlock::decNumOfFreeBlocksInFileSys() {
	numOfFreeBlocksInFileSys--;
}

void SuperBlock::incNumOfFreeInodesInFileSys() {
	numOfFreeINodesInFileSys++;
}

void SuperBlock::decNumOfFreeInodesInFileSys() {
	numOfFreeINodesInFileSys--;
}


void SuperBlock::setPointerIntoBlockOfFreeBlocks(int newPointerIntoBlockOfFreeBlocks) {
	pointerIntoBlockOfFreeBlocks = newPointerIntoBlockOfFreeBlocks;
}

void SuperBlock::setPointerToTheLastBlockOfFreeBlocks(int newPointerToTheLastBlockOfFreeBlocks) {
	pointerToTheLastBlockOfFreeBlocks = newPointerToTheLastBlockOfFreeBlocks;
}

void SuperBlock::setNumOfFreeINodesInFileSys(int newNumOfFreeINodes) {
	numOfFreeINodesInFileSys = newNumOfFreeINodes;
}

void SuperBlock::setPointerIntoBlockOfFreeINodes(int newPointerIntoBlockOfFreeINodes) {
	pointerIntoBlockOfFreeINodes = newPointerIntoBlockOfFreeINodes;
}

void SuperBlock::setPointerToTheLastBlockOfFreeINodes(int newPointerToTheLastBlockOfFreeINodes) {
	pointerToTheLastBlockOfFreeINodes = newPointerToTheLastBlockOfFreeINodes;
}

void SuperBlock::writeToPhysicalDisk() {
	int sizeOfInt = sizeof(int);
	//goes to the location on the superblock (0)
	lseek(fileDescriptor,0,SEEK_SET);
	//writes the disk size
	write(fileDescriptor, &fileSysSize, sizeOfInt);
	//writes the disk size
	write(fileDescriptor, &sizeOfBlock, sizeOfInt);
	//writes the number of the root(/) i-node
	write(fileDescriptor, &numOfRootINode, sizeOfInt);
	//writes the number of free blocks in the file system
	write(fileDescriptor, &numOfFreeBlocksInFileSys, sizeOfInt);
	//writes the pointer into the block of free blocks of the file system
	write(fileDescriptor, &pointerIntoBlockOfFreeBlocks, sizeOfInt);
	//writes the pointer to the last block of free blocks of the file system
	write(fileDescriptor, &pointerToTheLastBlockOfFreeBlocks, sizeOfInt);
	//writes the size of the inode array of the file system
	write(fileDescriptor, &sizeOfINodeArray, sizeOfInt);
	//writes the number of the free inodes of the file system
	write(fileDescriptor, &numOfFreeINodesInFileSys, sizeOfInt);
	//writes the pointer into the block of free inodes of the file system
	write(fileDescriptor, &pointerIntoBlockOfFreeINodes, sizeOfInt);
	//writes the pointer to the last block of free inodes of the file system
	write(fileDescriptor, &pointerToTheLastBlockOfFreeINodes, sizeOfInt);

}

